﻿//  Copyright © Decebal Mihailescu 2013-2014
//  All rights reserved. This source code and binaries are distributed under 
//  Microsoft Public PatternLicense (Ms-PL)
//  The latest code is available at http://VSDesignPatterns.codeplex.com

//  Redistributions of source code must retain the above copyright notice, 
//  this list of conditions and the following disclaimer. 
//  Redistributions in binary form must reproduce the above copyright notice, 
//  this list of conditions and the following disclaimer in the documentation 
//  and/or other materials provided with the distribution. 

//  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
//  KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
//  IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
//  PURPOSE. IT CAN BE DISTRIBUTED FREE OF CHARGE AS LONG AS THIS HEADER 
//  REMAINS UNCHANGED.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using System.Xml;
using System.Xml.Linq;
using System.Xml.XPath;
using System.Reflection;
using System.IO;
using System.Threading;
using System.Diagnostics;
using System.Globalization;
using Microsoft.Win32;
using System.Security.Permissions;

namespace DesignPatternsWizard
{
    using Common;
#if !VS2008
    using System.Threading.Tasks;
#endif
    [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
    [System.Runtime.InteropServices.ComVisibleAttribute(true)]
    public partial class WizardForm : Form, IWizardWindow
    {
        internal IEnumerable<ILanguageProvider> _langProviders;
        internal readonly IProjectInfo _projectInfo;
        bool _bUserCancelling = false;
        public void ClientCallback(String patternName)
        {
            string pn = patternName.Trim().Replace(" ", "").ToLower();
            if (!_wizardPages.Templates.Any(itp => pn.Contains(itp.PatternName.ToLower())))
            {
                _toolStripStatusLabel.Text = string.Format("'{0}' is a unknown pattern or it is not made available by its language provider", patternName);
                return;
            }
            try
            {
                if (pn.Contains(_wizardPages.SelectedPattern.PatternName.ToLower()))
                    return;
                //sort the grid by first column
                _dataGridViewPatterns.Sort(_dataGridViewPatterns.Columns[0], ListSortDirection.Ascending);
                Application.DoEvents();
                //get the first row matching the pattern
                DataGridViewRow row = _dataGridViewPatterns.Rows.Cast<DataGridViewRow>()
               .FirstOrDefault(r => pn.Contains((r.DataBoundItem as ITemplatePattern).PatternName.ToLower()));
                if (row == null)
                {//should not happen
                    _toolStripStatusLabel.Text = string.Format("'{0}' is a unknown pattern or it is not made available by its language provider", pn);
                    return;
                }
                int ci = _dataGridViewPatterns.CurrentCell.ColumnIndex;
                //force the datagrid to change the current row and pattern
                _dataGridViewPatterns.CurrentCell = _dataGridViewPatterns.Rows[row.Index].Cells[ci];

            }
            catch (Exception ex)
            {
                _toolStripStatusLabel.Text = ex.Message;

            }

        }

        private WizardForm()
        {
            InitializeComponent();

        }
        public WizardForm(IProjectInfo projectInfo)
            : this()
        {
            _projectInfo = projectInfo;
            if (_projectInfo != null)
            {
                (_projectInfo as ProjectInfo).WizardWindow = this;

            }
        }
        bool _bShowNewVersionAvailable;

        private void WizardForm_Load(object sender, EventArgs e)
        {
            if (DesignMode)
                return;
            try
            {

                _wizardPages.SelectedIndex = 0;
                _buttonPrev.Enabled = false;
                _webBrowserDescription.AllowWebBrowserDrop = false;
                _webBrowserDescription.IsWebBrowserContextMenuEnabled = false;
                _webBrowserDescription.WebBrowserShortcutsEnabled = false;
                _webBrowserDescription.ObjectForScripting = this;
                _webBrowserDescription.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(_webBrowserDescription_DocumentCompleted);
                this.UseWaitCursor = true;
                foreach (Control c in this.Controls)
                    c.Enabled = false;
                _splitContainerVertical.Panel1Collapsed = !WizardUtils.ShowFiltersPanel;
                _buttonFiltersPanel.Text = _splitContainerVertical.Panel1Collapsed ? "Show Filters" : "Hide Filters";
                if (_projectInfo != null)
                {
#if VS2008
                    BackgroundWorker bw = new BackgroundWorker();
                    bw.DoWork += new DoWorkEventHandler((object snd, DoWorkEventArgs resultTask) =>
                    {
                        _langProviders = _projectInfo.CreateSpecificLanguageProviders(WizardUtils.IsProviderInUse);
                        CheckVersion();
                        IEnumerable<ITemplatePattern> templates = LoadPatterns(_langProviders);
                        resultTask.Result = (templates == null || templates.Any()) ? new SortableBindingList<ITemplatePattern>(templates.ToList()) : null;
                    });
                    bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler((object snd, RunWorkerCompletedEventArgs resultTask) =>

#else
                    Task<SortableBindingList<ITemplatePattern>> tsk = new Task<SortableBindingList<ITemplatePattern>>(() =>
                        {
                            _langProviders = _projectInfo.CreateSpecificLanguageProviders(WizardUtils.IsProviderInUse);
                            CheckVersion();
                            IEnumerable<ITemplatePattern> templates = LoadPatterns(_langProviders);

                            return (templates == null || templates.Any()) ? new SortableBindingList<ITemplatePattern>(templates.ToList()) : null;
                        });
                    tsk.ContinueWith(resultTask =>
#endif

                    {
                        try
                        {
                            this.UseWaitCursor = false;
                            foreach (Control c in this.Controls)
                                c.Enabled = true;

                            _wizardPages.Templates = null;
                            if (_langProviders == null)
                            {
                                MessageBox.Show(this, string.Format("the {0} does not have a coresponding LanguageProvider for {1}", _projectInfo.ProjectName, _projectInfo.CodeLang));
                                _buttonNext.Enabled = false;
                                return;
                            }

#if VS2008
                            if (resultTask.Error != null)
                            {
                                _toolStripStatusLabel.Text = "Unable to load Design Templates because " + resultTask.Error.Message;
                                return;
                            }
#endif

                            Text += string.Format(" - Project: {0}, Lang:{1}, Assembly Version:{2}",
                                _projectInfo.ProjectName, _projectInfo.CodeLang, MEFController.Instance.DPEntryAssembly.GetName().Version);//_langProviders.First().PatternsVersion);
#if DEBUG
                            Text += ":Debug";
#endif
                            if (resultTask.Result != null)
                            {
                                _wizardPages.Templates = resultTask.Result as SortableBindingList<ITemplatePattern>;
                                _dataGridViewPatterns.DataSource = _wizardPages.Templates;
                                _lblCrtVSVer.Text = string.Format("The current VS version is {0}", Utils.VSVersion);//ipi.VisualStudioVersion);
                                SetFilters();
                                ShowColumns(); //invoked by FilterComboBox_SelectedValueChanged too
                                try
                                {
                                    string culture = (InputLanguage.CurrentInputLanguage.Culture.Parent == null) ? InputLanguage.CurrentInputLanguage.Culture.DisplayName : InputLanguage.CurrentInputLanguage.Culture.Parent.DisplayName;
                                    _labelLang.Text += culture;
                                }
                                catch (Exception)
                                { }
                                _comboBoxCulture.SelectedItem = InputLanguage.CurrentInputLanguage.Culture.ThreeLetterISOLanguageName;
                                _toolStripStatusLabel.Text = string.Format("Loaded {0} {1} software patterns in {2} ms",
                                    _wizardPages.Templates.Count(), _projectInfo.CodeLang, System.Convert.ToUInt32(_projectInfo.LoadingTime.TotalMilliseconds));
                            }
                            _bformLoaded = true;

                            if (!_langProviders.Any(lp =>
                                {
                                    ILanguageProviderMetaData ilpmd = lp.GetAsService<ILanguageProviderMetaData>();
                                    if (_projectInfo == null || ilpmd == null)
                                        return false;
                                    return _projectInfo.CodeLang == ilpmd.SupportedLangs;
                                }))
                            {
                                _buttonNext.Enabled = false;
                                //register automatically only if it is an extension
                                bool bIsExt = false;
#if VS2015
                                try
                                {
                                    // IPackageInstall ipi = VSWindow as IPackageInstall;
                                    IServiceProvider isp = VSWindow as IServiceProvider;
                                    if (isp != null)
                                    {
                                        IPackageInstall ipi = isp.GetAsService<IPackageInstall>();
                                        if (ipi != null)
                                            ipi.PostInstallPackage(this);
                                    }


                                }
                                catch (Exception ex)
                                {
                                    Logging.Instance.Log(1, "Initialization Error in VSDesignPackage before registering the providers" + ex.Message);
                                    //  MessageBox.Show(ex.Message, "Exception in Package initialization");
                                    //We can ignore that errors
                                }
                                string loc = this.GetType().Assembly.Location.ToUpper();
                                bIsExt = (loc.Contains(@"\MICROSOFT VISUAL STUDIO") && loc.Contains(@"\COMMON7\IDE\EXTENSIONS\"))
                                    || loc.Contains(@"\MICROSOFT\VISUALSTUDIO\"+ Utils.VSVersion + @"\EXTENSIONS\");
                             //   this.ShowMessageBox(loc, bIsExt.ToString());
#endif
                                if (bIsExt)
                                {
                                    bool bpReg = false;
                                    foreach (var lp in MEFController.Instance.GetLPInstatntiated(null))
                                    {
                                        bpReg |= lp.Value.RegisterLP(true, null, null, this);

                                    }

                                    if (bpReg)
                                    {
                                        _toolStripStatusLabel.Text = string.Format("First time registration for the language providers");
                                        ProjectInfo.RefreshLangProviders();
                                        WizardForm_Load(null, null);
                                        SetFilters();
                                    }
                                }
                                else
                                {
                                    MessageBox.Show(this, string.Format("There is no provider in use for {0}.\r\nPlease Select at least one!", _projectInfo.CodeLang), "Can't find templates");
                                    ConfigForm cf = new ConfigForm(2);
                                    if (cf.ShowDialog(this) == DialogResult.OK)
                                    {
                                        WizardForm_Load(cf, null);
                                        SetFilters();
                                    }
                                    return;
                                }




                            }
                            HandleRegistration();
                            _dataGridViewPatterns.Focus();

                            if (Utils.SortPatternsOnLoad)
                            {
                                Application.DoEvents();
                                //sort the grid by first column
                                _dataGridViewPatterns.Sort(_dataGridViewPatterns.Columns[0], ListSortDirection.Ascending);
                            }

                        }
                        catch (Exception ex)
                        {
                            _toolStripStatusLabel.Text = string.Format("Exception thrown while loading patterns:{0}", ex.Message);
                        }
#if VS2008
                    });
                    bw.RunWorkerAsync();

#else
                    }, TaskScheduler.FromCurrentSynchronizationContext());
                    tsk.Start();
#endif
                }//end if  if (ipi != null && lp != null)
                this.CenterToParent();


            }
            catch (Exception ex)
            {
                _toolStripStatusLabel.Text = string.Format("Exception thrown while loading patterns:{0}", ex.Message);
            }

        }

        void _webBrowserDescription_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            WebBrowser wb = sender as WebBrowser;
            if (Utils.CollapseHeaders)
            {
                // wb.Document.InvokeScript("ChangeAppearance", new String[] { "show", "last" });
                wb.Document.InvokeScript("ChangeAppearance", new object[] { "show", (Utils.StartExpanded ? "all" : "first"), Utils.Expand, Utils.Collapse, Utils.Collapse.Length });
                // wb.Document.InvokeScript("DisablePatternLinks", new String[] { });
            }
            else
            {
                wb.Document.InvokeScript("ChangeAppearance", new String[] { "show", "none" });
            }
        }

        private void HandleRegistration()
        {
            if (WizardUtils.HasEscalatedPrivileges(System.Security.Principal.WindowsBuiltInRole.Administrator))
                this.Text += "(Administrator)";
            if (_bShowNewVersionAvailable)
            {

                AskForUpgrade(this);
            }
            else
            {
                float onlineVer = float.Parse(Utils.LastOnlineVer, CultureInfo.InvariantCulture.NumberFormat);
                AssemblyName an = MEFController.Instance.DPEntryAssembly.GetName();
                int onlineNo = Convert.ToInt32(onlineVer * 100);
                int assno = an.Version.Major * 100 + an.Version.Minor;
                if (onlineNo > assno)
                {
                    try
                    {
                        _notifyIcon.Visible = true;
                        _notifyIcon.ShowBalloonTip(200, "A new version is available",
                            string.Format("Download Design Patterns{0}version {1}", Environment.NewLine, onlineVer.ToString(CultureInfo.InvariantCulture.NumberFormat)),
                            ToolTipIcon.Info);

                    }
                    catch (Exception ex)
                    {

                        _toolStripStatusLabel.Text = string.Format("Exception thrown while notifying:{0}", ex.Message);
                    }
                }

            }
            if (MEFController.Instance.HandleTrialActivation != null)
                MEFController.Instance.HandleTrialActivation(this);
            //HandleTrialActivation(this);
        }

        internal static void AskForUpgrade(IWin32Window parent)
        {
            if (DialogResult.Yes == MessageBox.Show(parent, string.Format("Version {0} has become available{1}Do you want to download it now?",
                Utils.LastOnlineVer, Environment.NewLine),
                "An update is available online", MessageBoxButtons.YesNo, MessageBoxIcon.Question))
            {
                string downloadUrl;
                float onlineVersion;
                //remove the time component to signal that the user saw the upgrade Msg
                Utils.LastOnlineCheck = DateTime.Today;
                if (Utils.NewOnlineVersionExists(out downloadUrl, out onlineVersion))
                {
                    System.Diagnostics.Process.Start(string.IsNullOrEmpty(downloadUrl) ? Utils.BaseURL : downloadUrl);
                }
            }
            else
                Utils.LastOnlineCheck = Utils.LastOnlineCheck.Date;
        }
        IEnumerable<ITemplatePattern> LoadPatterns(IEnumerable<ILanguageProvider> lps)
        {
            List<ITemplatePattern> lst = new List<ITemplatePattern>();
            foreach (ILanguageProvider lp in lps)
            {
                try
                {
                    lst.AddRange(lp.LoadTemplates(this));
                }
                catch (Exception ex)
                {

                    Logging.Instance.Log(1, "Exception thrown by ILanguageProvider.LoadTemplates :{0}", ex.Message);
                }
            }
            RemoveDuplicateTemplates(lst);
            return lst;
        }

        private static void RemoveDuplicateTemplates(List<ITemplatePattern> lst)
        {
            //group by pattern name
            ILookup<string, ITemplatePattern> lookup = lst.ToLookup(p => (p.PatternName /*+ p.MinVSVersion +p.ProgrammingStyle+p.CompilerSyntax +p.Culture*/).ToLower(), p => p);

            foreach (IGrouping<string, ITemplatePattern> templateGroup in lookup)
            {
                //if it has both free and licensed templates with the same name, remove them using the TemplateVersion (0= free)
                int premCnt = templateGroup.Count(t => t.TemplateVersion > 0);
                if (premCnt > 0 && premCnt < templateGroup.Count())
                {
                    //remove non licensed free templates 
                    foreach (ITemplatePattern t in templateGroup.Where(x => x.TemplateVersion == 0))
                    {
                        lst.Remove(t);
                    }

                }
            }
        }
        private void CheckVersion()
        {
            DateTime lastCheck = Utils.LastOnlineCheck;
            bool bFirstTime = Utils.LastOnlineVer == "9.9" && lastCheck < DateTime.Now;
            if (bFirstTime)
            {
                Version v = MEFController.Instance.DPEntryAssembly.GetName().Version;
                string crtVersion = string.Format("{0}.{1}", v.Major, v.Minor);

                Utils.LastOnlineVer = crtVersion;
                //remove the time component to signal that the user saw the upgrade Msg
                Utils.LastOnlineCheck = DateTime.Today;

                _bShowNewVersionAvailable = false;
            }
            else
            {//not the first time
                _bShowNewVersionAvailable = Utils.IsNewerThanCurrent(float.Parse(Utils.LastOnlineVer, System.Globalization.CultureInfo.InvariantCulture.NumberFormat));
                _bShowNewVersionAvailable &= lastCheck != lastCheck.Date && lastCheck < DateTime.Now;
            }
        }

        private void SetFilters()
        {
            if (_wizardPages.Templates == null)
                return;
            //select the first row
            List<string> cbxData = new List<string>(new string[] { "Any" });
            cbxData.AddRange(_wizardPages.Templates.Where(p => p.CompilerSyntax != null).Select(t => t.CompilerSyntax).Distinct());
            _comboBoxCompilerSyntax.DataSource = cbxData.ToArray();//make a copy since cbxData is reused
            AssociateFilters2Columns(_comboBoxCompilerSyntax, ColumnsEnum.CompilerSyntax);


            cbxData.Clear();
            cbxData.Add("Any");
            cbxData.AddRange(_wizardPages.Templates.Where(p => p.ProgrammingStyle != null).Select(t => t.ProgrammingStyle).Distinct());
            _comboBoxProgrammingStyle.DataSource = cbxData.ToArray();
            AssociateFilters2Columns(_comboBoxProgrammingStyle, ColumnsEnum.ProgrammingStyle);


            cbxData.Clear();
            cbxData.Add("Any");
            cbxData.AddRange(_wizardPages.Templates.Where(p => p.MinVSVersion != 0.0f).Select(t => t.MinVSVersion.ToString()).Distinct());
            _comboBoxMinVSVersion.DataSource = cbxData.ToArray();
            AssociateFilters2Columns(_comboBoxMinVSVersion, ColumnsEnum.MinVSVersion);

            cbxData.Clear();
            cbxData.Add("Any");
            cbxData.AddRange(_wizardPages.Templates.Where(p => p.Category != null).Select(t => t.Category).Distinct());
            _comboBoxCategory.DataSource = cbxData.ToArray();
            AssociateFilters2Columns(_comboBoxCategory, ColumnsEnum.Category);

            cbxData.Clear();
            cbxData.Add("Any");
            cbxData.AddRange(_wizardPages.Templates.Where(p => p.Culture != null).Select(t => t.Culture).Distinct());
            _comboBoxCulture.DataSource = cbxData.ToArray();
            //http://stackoverflow.com/questions/3063320/combobox-adding-text-and-value-to-an-item-no-binding-source
            //_comboBoxCulture.DataSource = cbxData.Select(e => new { Text = e, Value = e }).ToArray(); 
            //_comboBoxCulture.DisplayMember = "Text";
            //_comboBoxCulture.ValueMember = "Value";//will crash when called too early
            AssociateFilters2Columns(_comboBoxCulture, ColumnsEnum.Culture);
        }

        private void AssociateFilters2Columns(ComboBox cbx, ColumnsEnum colEnum)
        {
            DataGridViewColumn column = _dataGridViewPatterns.Columns[colEnum.ToString()];
            column.Tag = cbx;//make associations
            cbx.Tag = column;
        }


        private void ShowColumns()
        {
            if (_dataGridViewPatterns.DataSource == null || _dataGridViewPatterns.Rows.Count == 0)
            {
                _buttonNext.Enabled = false;
                return;
            }
            _dataGridViewPatterns.Columns["Arguments"].Visible = false;
            _dataGridViewPatterns.Columns["TemplateFiles"].Visible = false;
            _dataGridViewPatterns.Columns["Picture"].Visible = false;
            _dataGridViewPatterns.Columns["Description"].Visible = false;
            _dataGridViewPatterns.Columns["CodeLanguage"].Visible = false;
            _dataGridViewPatterns.Columns["OnlineResources"].Visible = false;
            _dataGridViewPatterns.Columns["PictureStoredAs"].Visible = false;
            _dataGridViewPatterns.Columns["DescriptionStoredAs"].Visible = false;
            _dataGridViewPatterns.Columns["TemplateVersion"].Visible = false;
            ColumnsEnum cols = WizardUtils.Columns;
            ColumnsEnum[] allColumns = Utils.GetAllEnumValues<ColumnsEnum>();
            foreach (ColumnsEnum col in allColumns)
            {

                switch (col)
                {
                    case ColumnsEnum.Culture:
                        SetColumn(cols, col, _comboBoxCulture, _dataGridViewPatterns);
                        break;
                    case ColumnsEnum.Category:
                        SetColumn(cols, col, _comboBoxCategory, _dataGridViewPatterns);
                        break;
                    case ColumnsEnum.ProgrammingStyle:
                        SetColumn(cols, col, _comboBoxProgrammingStyle, _dataGridViewPatterns);
                        break;
                    case ColumnsEnum.CompilerSyntax:
                        SetColumn(cols, col, _comboBoxCompilerSyntax, _dataGridViewPatterns);
                        break;
                    case ColumnsEnum.MinVSVersion:
                        SetColumn(cols, col, _comboBoxMinVSVersion, _dataGridViewPatterns);
                        break;
                    default://this is the pattern alias that can't be filtered
                        _dataGridViewPatterns.Columns[col.ToString()].Visible = (cols & col) != default(ColumnsEnum);
                        break;

                }
                //this might be redundant most of the times
                _dataGridViewPatterns.Columns[col.ToString()].DataPropertyName = col.ToString();

            }
            Application.DoEvents();

        }

        private static void SetColumn(ColumnsEnum cols, ColumnsEnum col, ComboBox cbx, DataGridView dgr)
        {
            bool unfiltered = false;
            string selVal = cbx.SelectedValue == null ? null : cbx.SelectedValue.ToString();
            unfiltered = (string.IsNullOrEmpty(selVal) || selVal == "Any");
            cbx.Enabled = (cols & col) != default(ColumnsEnum);
            if (!cbx.Enabled)// avoid extra filtering
                cbx.SelectedItem = "Any";
            DataGridViewColumn column = dgr.Columns[col.ToString()];
            if (column != null)
                column.Visible = unfiltered && cbx.Enabled;

        }


        private void _wizardPages_SelectedIndexChanged(object sender, EventArgs e)
        {
            int index = _wizardPages.SelectedIndex;
            switch (index)
            {
                case 0:
                    _buttonNext.Text = "&Next";
                    _buttonPrev.Enabled = false;
                    break;
                case 1:
                    ITemplatePattern iSelTP = _wizardPages.SelectedPattern;
                    bool bCanGenerate = iSelTP != null && iSelTP.CanGeneratePattern(this);
                    if (bCanGenerate)
                    {
                        _buttonNext.Text = "&Next";
                        _buttonPrev.Enabled = true;
                        //populate using _wizardPages.SelectedPattern
                        LoadTemplateArguments(iSelTP);
                        if (_dataGridViewCustomParams.DataSource == null)
                            _buttonNext.Enabled = false;//should  not happen
                    }
                    else
                    {
                        _buttonNext.Text = "&Next";
                        _buttonNext.Enabled = false;
                        _buttonPrev.Enabled = true;

                        _dataGridViewCustomParams.DataSource = null;
                        _dataGridViewCustomParams.Tag = null;
                        _dataGridViewCustomParams.Refresh();
                        _dataGridViewRuntimeParams.DataSource = null;
                        _dataGridViewRuntimeParams.Tag = null;
                        _dataGridViewRuntimeParams.Refresh();


                        // bool bCanGenerate = CanGeneratePattern(iSelTP);
                        // bool bCanGenerate = iSelTP.CanGeneratePattern(this);
                        if (this.IsRestarting)
                            Close();
                        return;
                    }

                    break;
                case 2:
                    int i = 0;
                    _tabControlFiles.SuspendLayout();
                    _tabControlFiles.Controls.Clear();
                    if (_wizardPages.SelectedPattern.TemplateFiles != null)
                    {
                        _wizardPages.SelectedPattern.Arguments = (_dataGridViewCustomParams.DataSource as ITemplateArgument[]).Concat(_dataGridViewRuntimeParams.DataSource as ITemplateArgument[]).ToArray();
                        foreach (ITemplateFile itf in _wizardPages.SelectedPattern.TemplateFiles)
                        {
                            _tabControlFiles.Controls.Add(new FilePage(itf, i++));
                        }
                    }
                    _tabControlFiles.ResumeLayout(true);
                    this.PerformLayout();
                    if (i > 0)
                    {
                        _buttonNext.Text = "&Generate";
                        _buttonPrev.Enabled = true;
                    }
                    else
                        _toolStripStatusLabel.Text = string.Format("The Template '{0}' has no files", _wizardPages.SelectedPattern.PatternName);
                    break;
                default:
                    return;
            }

            IPageWizard ipage = _wizardPages.SelectedTab as IPageWizard;
            if (this._langProviders.FirstOrDefault() != null && ipage != null)
            {
                ITabWizard itw = this._wizardPages as ITabWizard;
                ILanguageProvider ilp = itw.SelectedPattern.GetAsService<ILanguageProvider>();
                EventValidaton evval = ipage.Validate(index, ilp);
                _buttonNext.Enabled = evval.Result == ResultEnum.Success;
                if (evval.ErrorMsg != null && !_buttonNext.Enabled)
                    _toolStripStatusLabel.Text = evval.ErrorMsg;
                else
#if DEBUG

                    _toolStripStatusLabel.Text = string.Format(" _SelectedIndex = {0}, Name:{1}", index, sender.ToString());
#else
                    _toolStripStatusLabel.Text = string.Empty;
#endif

            }
        }

        private void LoadTemplateArguments(ITemplatePattern itp)
        {
            //avoid updates if the parent template is the same
            if (itp != _dataGridViewCustomParams.Tag && itp.Arguments != null)
            {
                _dataGridViewCustomParams.Tag = itp;
                _dataGridViewCustomParams.DataSource = itp.Arguments.OfType<TemplateArgument>().ToArray();
                _dataGridViewCustomParams.Columns["IsRuntime"].Visible = false;
                _dataGridViewCustomParams.Columns["ArgumentName"].ReadOnly = true;
                _dataGridViewCustomParams.Columns["Description"].ReadOnly = true;
            }
            //else
            //    _dataGridViewCustomParams.DataSource = null;

            if (_dataGridViewRuntimeParams.Tag != itp && itp.Arguments != null)
            {
                _dataGridViewRuntimeParams.Tag = itp;
                _dataGridViewRuntimeParams.DataSource = itp.Arguments.OfType<TemplateRuntimeArgument>().ToArray();
                _dataGridViewRuntimeParams.Columns["IsRuntime"].Visible = false;
                _dataGridViewRuntimeParams.Columns["ArgumentName"].ReadOnly = true;
                _dataGridViewRuntimeParams.Columns["Description"].ReadOnly = true;
            }
            //else
            //    _dataGridViewRuntimeParams.DataSource = null;
        }

        private void _buttonNext_Click(object sender, EventArgs e)
        {
            switch (_wizardPages.SelectedIndex)
            {
                case 2:
                    float VSversion = float.Parse(Utils.VSVersion, CultureInfo.InvariantCulture.NumberFormat);
                    if (VSversion < _wizardPages.SelectedPattern.MinVSVersion &&
                        MessageBox.Show(this,
                        "The VS version is lower than the pattern's VS version.\r\nDo you still want to generate the code?",
                        "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.No)
                    {
                        _wizardPages.SelectedIndex = 0;
                    }
                    else
                        Close();
                    break;
                case 1:
                    _wizardPages.SelectedIndex += 1;//to transfer data to the crt pattern
                    Application.DoEvents();
                    ILanguageProvider ilp = _wizardPages.SelectedPattern.GetAsService<ILanguageProvider>();
                    var badArg = _wizardPages.SelectedPattern.Arguments.FirstOrDefault(a => !ilp.IsValidArgument(a));
                    if (badArg != null)
                    {
                        MessageBox.Show(this, string.Format("the value '{0}' for argument {1} is invalid", badArg.Value, badArg.ArgumentName),
                            "Please fix the error in order to continue!", MessageBoxButtons.OK, MessageBoxIcon.Hand);
                        _wizardPages.SelectedIndex -= 1;//roll back
                    }
                    break;
                default:
                    _wizardPages.SelectedIndex += 1;
                    break;
            }
        }

        private void _buttonCancel_Click(object sender, EventArgs e)
        {
            _bUserCancelling = true;
            Close();
        }

        private void _buttonPrev_Click(object sender, EventArgs e)
        {
            if (_wizardPages.SelectedIndex == 0)
                return;
            _wizardPages.SelectedIndex -= 1;
        }


        private void WizardForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            try
            {
                UseWaitCursor = true;
                Application.DoEvents();
                switch (e.CloseReason)
                {
                    case CloseReason.UserClosing:
                        if (!_bUserCancelling && !this.IsRestarting)
                        {
                            try
                            {
                                _buttonNext.Enabled = false;
                                Application.DoEvents();
                                var lp = this.GetAsService<ILanguageProvider>();
                                EventGeneration evg = new EventGeneration() { LangProvider = lp, Result = ResultEnum.UnknownError, Url = _wizardPages.SelectedPattern.OnlineResources };
                                evg.Files = lp.GenerateCodeFiles(_wizardPages.SelectedPattern).Where(n => n != null).ToArray();
                                if (evg.Files == null || evg.Files.Length < 1)
                                {
                                    evg.Result = ResultEnum.UnknownError;
                                    evg.ErrorMsg = "Can't generate from bad template";
                                    _toolStripStatusLabel.Text = evg.ErrorMsg;
                                    e.Cancel = true;
                                    return;
                                }
                                IProjectInfo ipi = lp.GetAsService<IProjectInfo>();
                                ipi.OnUpdateVSProject(this, evg);
                                e.Cancel = evg.Result != ResultEnum.Success;
                                if (evg.ErrorMsg != null && e.Cancel)
                                {
                                    MessageBox.Show(this, evg.ErrorMsg, "DesigPatterWizard", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                                    _toolStripStatusLabel.Text = evg.ErrorMsg;
                                }
                                else
                                    _toolStripStatusLabel.Text = "";
                            }
                            finally
                            {
                                _buttonNext.Enabled = true;
                            }
                        }
                        break;
                    case CloseReason.ApplicationExitCall:
                        break;
                    case CloseReason.None:
                        e.Cancel = false;
                        break;
                    default:
                        break;
                }
            }
            finally
            {
                UseWaitCursor = false;
            }
        }

        private void WizardForm_FormClosed(object sender, FormClosedEventArgs e)
        {
            if (WizardWindowClosed != null)
                WizardWindowClosed(sender, new EventWizardWindowClosed() { CloseReason = (int)e.CloseReason });
            if (Utils.LastOnlineCheck + new TimeSpan(WizardUtils.DaysToCheckOnline, 0, 0, 0) < DateTime.Today)// < is correct
            {//check only if older than 15 days

                Thread tr = new Thread(new ThreadStart(() =>
                {
                    string downloadUrl;
                    float onlineVersion;
                    //keep the time component to signal that the user haven't seen the upgrade Msg
                    Utils.LastOnlineCheck = DateTime.Now;
                    Utils.NewOnlineVersionExists(out downloadUrl, out onlineVersion);
                }));
                tr.IsBackground = false;
                tr.Start();
            }
        }
        #region Overrides

        protected override void WndProc(ref Message m)
        {

            switch ((Msg)m.Msg)
            {
                case Msg.WM_CREATE:
                    break;

                case Msg.WM_ACTIVATE:

                    break;
                case Msg.WM_SYSCOMMAND:
                    if (m.HWnd == this.Handle && (int)m.WParam == (int)SystemCommands.SC_CLOSE)
                        _bUserCancelling = true;
                    break;
                case Msg.WM_CLOSE:
                    break;
                case Msg.WM_DESTROY:
                    break;
                case Msg.WM_NCDESTROY:

                case Msg.WM_QUIT:
                    break;
                case Msg.WM_COMMAND:
                    switch (NativeMethods.GetDlgCtrlID(m.LParam))
                    {
                        case (int)ControlsId.ButtonOk://OK
                            break;
                        case (int)ControlsId.ButtonCancel://Cancel
                            break;
                        case (int)ControlsId.ButtonHelp://help
                            break;
                        case 0:
                            break;
                        default:
                            break;
                    }
                    break;
                default:
                    break;
            }//switch ((Msg)m.Msg) ends
            base.WndProc(ref m);
        }
        #endregion

        #region IProjectInfo Members

        public string FileName { get; set; }

        public string Language { get; set; }
        public string VisualStudioVersion { get; set; }

        public Dictionary<string, string> ProjectProperties { get; set; }

        #endregion

        #region IWizardWindow Members

        public bool IsRestarting { get; set; }
        public DialogResult ShowWizardWindow(IWin32Window parent)
        {
            this.Show(parent);
            return DialogResult.OK;
        }
        public PictureBox Diagram { get { return _pictureBox; } }
        public RichTextBox RTBDescription { get { return _richTextBoxDescription; } }
        public WebBrowser WBDescription { get { return _webBrowserDescription; } }
        public LinkLabel OnlineResources { get { return this._linkLabelOnlineResources; } }
        public IWin32Window VSWindow { get; set; }


        public event WizardWindowClosedDelegate WizardWindowClosed;

        #endregion

        #region IServiceProvider Members

        public new object GetService(Type serviceType)
        {
            if (serviceType == typeof(IWizardWindow) || serviceType == typeof(IServiceProvider))
                return this;
            if (serviceType == typeof(IEnumerable<ILanguageProvider>) && _langProviders != null)
                return _langProviders;
#if VS2015
            if (serviceType == typeof(IPackageInstall))
                return this.VSWindow;
#endif
            if (serviceType == typeof(IProjectInfo) && _projectInfo != null)
                return _projectInfo;
            object res = null;
            if (res != null)
                return res;
            if (serviceType == typeof(ILanguageProvider) || serviceType == typeof(ILanguageProviderMetaData))
            {
                if (_bformLoaded)
                {
                    ITabWizard itw = this._wizardPages as ITabWizard;
                    if (itw.SelectedPattern == null)
                        return null;
                    res = itw.SelectedPattern.GetService(serviceType);
                }
                else
                    res = (_langProviders == null || _langProviders.FirstOrDefault() == null) ? null : _langProviders.FirstOrDefault().GetService(serviceType);
            }
            if (res != null)
                return res;
            if (serviceType == typeof(ITabWizard))
                return _wizardPages;
            if (res == null)
                res = base.GetService(serviceType);
            return res;
        }

        #endregion
        bool _bformLoaded = false;
        private void FilterComboBox_SelectedValueChanged(object sender, EventArgs e)
        {
            ComboBox cb = sender as ComboBox;
            if (cb == null)
                return;
            string selVal = cb.SelectedValue as string;

            if (_bformLoaded)
            {
                if (cb.Tag != null)
                {
                    ColumnsEnum cols = WizardUtils.Columns;
                    DataGridViewColumn dgvc = cb.Tag as DataGridViewColumn;
                    string columnName = dgvc.Name;
                    ColumnsEnum col = (ColumnsEnum)Enum.Parse(typeof(ColumnsEnum), columnName, true);
                    SetColumn(cols, col, cb, _dataGridViewPatterns);
                }
                else
                {
                }

            }

            IEnumerable<ITemplatePattern> filteredTemplates = _wizardPages.Templates;//must be already enumerated (array)
            if (filteredTemplates == null)
                return;
            //filter the templates
            selVal = _comboBoxMinVSVersion.SelectedValue as string;
            if (!string.IsNullOrEmpty(selVal) && selVal != "Any")
                filteredTemplates = filteredTemplates.Where(t => t.MinVSVersion >= Convert.ToSingle(selVal)).ToArray();

            selVal = _comboBoxCompilerSyntax.SelectedValue as string;
            if (!string.IsNullOrEmpty(selVal) && selVal != "Any")
                filteredTemplates = filteredTemplates.Where(t => string.Compare(t.CompilerSyntax, selVal, true) == 0).ToArray();

            selVal = _comboBoxProgrammingStyle.SelectedValue as string;
            if (!string.IsNullOrEmpty(selVal) && selVal != "Any")
                filteredTemplates = filteredTemplates.Where(t => string.Compare(t.ProgrammingStyle, selVal, true) == 0).ToArray();

            selVal = _comboBoxCategory.SelectedValue as string;
            if (!string.IsNullOrEmpty(selVal) && selVal != "Any")
                filteredTemplates = filteredTemplates.Where(t => string.Compare(t.Category, selVal, true) == 0).ToArray();

            selVal = _comboBoxCulture.SelectedValue as string;
            if (!string.IsNullOrEmpty(selVal) && selVal != "Any")
                filteredTemplates = filteredTemplates.Where(t => string.Compare(t.Culture, selVal, true) == 0).ToArray();

            _dataGridViewPatterns.DataSource = new SortableBindingList<ITemplatePattern>(filteredTemplates);
        }

        private void _linkLabelOnlineResources_Click(object sender, EventArgs e)
        {
            System.Diagnostics.Process p = new System.Diagnostics.Process();
            if (_linkLabelOnlineResources.Links.Count == 0 || _linkLabelOnlineResources.Links[0].LinkData == null)
                return;
            p.StartInfo.FileName = _linkLabelOnlineResources.Links[0].LinkData.ToString();
            p.Start();
        }

        private void _dataGridViewPatterns_RowEnter(object sender, DataGridViewCellEventArgs e)
        {
            DataGridView dgv = sender as DataGridView;
            if (dgv == null)
                return;
            IList<ITemplatePattern> patterns = dgv.DataSource as IList<ITemplatePattern>;
            if (patterns == null || e.RowIndex < 0)
            {
                _wizardPages.SelectedPattern = null;
                return;
            }
            try
            {
                ITemplatePattern itp = dgv.Rows[e.RowIndex].DataBoundItem as ITemplatePattern; //patterns[e.RowIndex];
                DisplayPattern(itp);

            }
            catch (Exception ex)
            {
                _toolStripStatusLabel.Text = ex.Message;

            }

        }

        ITemplatePattern _lastPatternSelected = null;
        private void DisplayPattern(ITemplatePattern itp)
        {
            _wizardPages.SelectedPattern = itp;
            //this is done to improve startup and refresh performance
            if (itp == null || _lastPatternSelected == itp)// || (_lastPatternSelected != null && _lastPatternSelected.PatternName == itp.PatternName))
                return;
            _lastPatternSelected = itp;
            _buttonNext.Enabled = true;
            ITabWizard itw = _wizardPages;
            //  ITemplatePattern itp = itw.SelectedPattern;
            IRepository irep = itp.GetAsService<IRepository>();
            irep.UpdateDescription(itp, this);
            if (itp.Picture == null)
            {
                _toolStripStatusLabel.Text = "Missing picture for " + itp.PatternName;
                this.Diagram.Tag = null;
                this._pictureBox.Image = null;
            }
            else
                irep.UpdatePicture(itp, this);
            if (_linkLabelOnlineResources.Visible)
            {
                _linkLabelOnlineResources.Links.Clear();
                string str = "OnlineResources:" + _wizardPages.SelectedPattern.OnlineResources.Substring(0, Math.Min(50, _wizardPages.SelectedPattern.OnlineResources.Length));
                _linkLabelOnlineResources.Text = str;
                _linkLabelOnlineResources.Links.Add("OnlineResources:".Length, str.Length,
                    "\"" + _wizardPages.SelectedPattern.OnlineResources + "\"");
            }
        }


        private void _dataGridViewPatterns_DataSourceChanged(object sender, EventArgs e)
        {
            DataGridView dgv = sender as DataGridView;
            IList<ITemplatePattern> patterns = dgv.DataSource as IList<ITemplatePattern>;
            if (patterns == null || patterns.Count == 0)
            {
                _buttonNext.Enabled = false;
                _richTextBoxDescription.Clear();
                _linkLabelOnlineResources.Links.Clear();
                _linkLabelOnlineResources.Text = "";
                Application.DoEvents();
                if (_pictureBox.Image != null)
                    _pictureBox.Image.Dispose();
                _pictureBox.Image = null;
                Application.DoEvents();
                if (_pictureBox.InitialImage != null)
                    _pictureBox.InitialImage.Dispose();
                _pictureBox.InitialImage = null;
                _pictureBox.Update();
                Application.DoEvents();
                _pictureBox.Refresh();
                _wizardPages.SelectedPattern = null;
                _toolStripStatusLabel.Text = "You have filtered out all patterns. Please change some filters or add other providers.";
            }
            else
            {
                _buttonNext.Enabled = true;
                if (_bformLoaded)
                    _toolStripStatusLabel.Text = string.Format("There are {0} design patterns to choose from", patterns.Count);
            }
        }


        private void _dataGridViewParams_CellEndEdit(object sender, DataGridViewCellEventArgs e)
        {
            DataGridView dgv = sender as DataGridView;
            ITemplateArgument tmpl = dgv.Rows[e.RowIndex].DataBoundItem as ITemplateArgument;
            tmpl.Value = dgv.Rows[e.RowIndex].Cells["Value"].FormattedValue.ToString();
        }

        private void _buttonConfig_Click(object sender, EventArgs e)
        {
            ConfigForm cfg = new ConfigForm(1);
            try
            {
                if (cfg.ShowDialog(this) == DialogResult.OK && !cfg._providersChanged)
                {
                    ShowColumns();
                }
                if (cfg._providersChanged)
                {
                    this._dataGridViewPatterns.DataSource = null;
                    this._richTextBoxDescription.Clear();
                    if (_pictureBox != null && _pictureBox.Image != null)
                        _pictureBox.Image.Dispose();
                    this._pictureBox.Image = null;
                    this._pictureBox.Refresh();
                    this._webBrowserDescription.Visible = false;
                    WizardForm_Load(cfg, null);
                }

            }
            catch (Exception ex)
            {

                Logging.Instance.Log(1, "Exception thrown in _buttonConfig_Click: {0}", ex.Message);
            }

        }

        private void _dataGridViewPatterns_MouseUp(object sender, MouseEventArgs e)
        {
            // Load context menu on right mouse click
            DataGridView dgv = sender as DataGridView;
            if (dgv != null && e.Button == MouseButtons.Right)
            {
                DataGridView.HitTestInfo hitTestInfo = dgv.HitTest(e.X, e.Y);
                switch (hitTestInfo.Type)
                {
                    case DataGridViewHitTestType.Cell:
                        _contextMenuStrip.Tag = hitTestInfo;
                        _contextMenuStrip.Items[0].Visible = true;
                        _contextMenuStrip.Items[0].Text = string.Format("Filter {0} to '{1}'", dgv.Columns[hitTestInfo.ColumnIndex].Name,
                            dgv.Rows[hitTestInfo.RowIndex].Cells[hitTestInfo.ColumnIndex].Value);
                        _contextMenuStrip.Items[0].Enabled = _dataGridViewPatterns.Columns[hitTestInfo.ColumnIndex].Tag != null;
                        _contextMenuStrip.Items[1].Text = string.Empty;
                        _contextMenuStrip.Items[1].Visible = false;
                        _contextMenuStrip.Items[2].Text = "Remove all Filters";
                        _contextMenuStrip.Items[3].Visible = true;
                        _contextMenuStrip.Show(dgv, new Point(e.X, e.Y));
                        break;
                    case DataGridViewHitTestType.ColumnHeader:
                        _contextMenuStrip.Tag = dgv.Columns[hitTestInfo.ColumnIndex];
                        _contextMenuStrip.Items[0].Text = string.Empty;
                        _contextMenuStrip.Items[0].Visible = false;
                        _contextMenuStrip.Items[1].Visible = true;
                        _contextMenuStrip.Items[1].Text = string.Format("Hide Column '{0}'", dgv.Columns[hitTestInfo.ColumnIndex].Name);
                        //don't hide 'PatternName'
                        _contextMenuStrip.Items[1].Enabled = string.Compare(dgv.Columns[hitTestInfo.ColumnIndex].Name, "PatternName", true) != 0;
                        _contextMenuStrip.Items[2].Text = "Show all Columns";
                        _contextMenuStrip.Items[3].Visible = false;
                        _contextMenuStrip.Show(dgv, new Point(e.X, e.Y));
                        break;

                    case DataGridViewHitTestType.None:
                        _contextMenuStrip.Tag = hitTestInfo;
                        _contextMenuStrip.Items[0].Visible = false;
                        _contextMenuStrip.Items[0].Text = string.Empty;
                        _contextMenuStrip.Items[1].Text = string.Empty;
                        _contextMenuStrip.Items[1].Visible = false;
                        _contextMenuStrip.Items[2].Text = "Remove all Filters";
                        _contextMenuStrip.Items[3].Visible = false;
                        _contextMenuStrip.Show(dgv, new Point(e.X, e.Y));
                        break;
                    default:
                        MessageBox.Show(this, string.Format("Type {0}", hitTestInfo.Type));
                        break;

                }
            }
        }

        private void _contextMenuStrip_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
        {
            if (e.ClickedItem == _contextMenuStrip.Items[0])
            {
                DataGridView.HitTestInfo hitTestInfo = e.ClickedItem.Owner.Tag as DataGridView.HitTestInfo;
                DataGridViewColumn column = _dataGridViewPatterns.Columns[hitTestInfo.ColumnIndex];
                column.Visible = false;
                ComboBox cbx = column.Tag as ComboBox;
                if (cbx != null)
                {
                    cbx.SelectedItem = _dataGridViewPatterns.Rows[hitTestInfo.RowIndex].Cells[hitTestInfo.ColumnIndex].Value;
                }


            }
            if (e.ClickedItem == _contextMenuStrip.Items[1])
            {
                DataGridViewColumn column = e.ClickedItem.Owner.Tag as DataGridViewColumn;
                column.Visible = false;
                ComboBox cbx = column.Tag as ComboBox;
                if (cbx != null)
                {
                    cbx.SelectedItem = "Any";
                    cbx.Enabled = false;
                }
                ColumnsEnum colEnum = (ColumnsEnum)Enum.Parse(typeof(ColumnsEnum), column.Name, true);
                WizardUtils.Columns ^= colEnum;


            }
            if (e.ClickedItem == _contextMenuStrip.Items[2])
            {
                DataGridView.HitTestInfo hitTestInfo = e.ClickedItem.Owner.Tag as DataGridView.HitTestInfo;
                if (hitTestInfo == null)
                {
                    ColumnsEnum[] allColumns = Utils.GetAllEnumValues<ColumnsEnum>();
                    WizardUtils.Columns = allColumns.Aggregate((acc, loc) => loc | acc);//restore all show
                }
                else
                {
                    for (int i = 0; i < _dataGridViewPatterns.Columns.Count; i++)
                    {
                        ComboBox cbx = _dataGridViewPatterns.Columns[i].Tag as ComboBox;
                        if (cbx == null)
                            continue;
                        cbx.SelectedItem = "Any";
                        cbx.Enabled = true;

                    }
                }
                ShowColumns();
            }
            if (e.ClickedItem == _contextMenuStrip.Items[3])
            {
                DataGridView.HitTestInfo hitTestInfo = e.ClickedItem.Owner.Tag as DataGridView.HitTestInfo;
                _contextMenuStrip.Close();
                Application.DoEvents();
                if (hitTestInfo == null)
                {
                    //ColumnsEnum[] allColumns = Utils.GetEnumValues<ColumnsEnum>();
                    //WizardUtils.Columns = allColumns.Aggregate((acc, loc) => loc | acc);//restore all show
                }
                else
                {
                    ILanguageProvider ilp = _wizardPages.SelectedPattern.GetAsService<ILanguageProvider>();
                    if (ilp != null)
                        ilp.AboutLP(this);

                }
            }
            if (e.ClickedItem == _contextMenuStrip.Items[4])
            {
                WizardUtils.ShowFiltersPanel = _splitContainerVertical.Panel1Collapsed;
                _splitContainerVertical.Panel1Collapsed = !_splitContainerVertical.Panel1Collapsed;
                _contextMenuStrip.Close();
                _buttonFiltersPanel.Text = _splitContainerVertical.Panel1Collapsed ? "Show Filters" : "Hide Filters";
                Application.DoEvents();

            }

        }

        private void _buttonAbout_Click(object sender, EventArgs e)
        {

            IAboutWnd a = MEFController.Instance.AboutWnd ?? new FormAbout();
            a.ShowDialog(this);
            if (this.IsRestarting)
                Close();
        }

        private void _webBrowserDescription_VisibleChanged(object sender, EventArgs e)
        {
            if (_tabControlTemplateDetail.Visible && _tabControlTemplateDetail.SelectedTab == _tabPageDescription)
                _richTextBoxDescription.Visible = !_webBrowserDescription.Visible;
        }

        private void _richTextBoxDescription_VisibleChanged(object sender, EventArgs e)
        {
            if (_tabControlTemplateDetail.Visible && _tabControlTemplateDetail.SelectedTab == _tabPageDescription)
                _webBrowserDescription.Visible = !_richTextBoxDescription.Visible;
        }
        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            if (_langProviders != null)
                foreach (var lp in _langProviders)
                {
                    IDisposable ilp = lp as IDisposable;
                    if (ilp != null)
                        ilp.Dispose();
                }
            base.Dispose(disposing);
        }
        public void LoadImageFromStream(Stream strp)
        {
            _pictureBox.Image = Image.FromStream(strp);
        }
        private void _dataGridViewPatterns_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
        {
            DataGridView dgv = sender as DataGridView;
            if (dgv != null && dgv.Columns[e.ColumnIndex].Visible)
            {
                ITemplatePattern itp = dgv.Rows[e.RowIndex].DataBoundItem as ITemplatePattern;
                itp.UIFormatTemplatePattern(e);

            }

        }
        private void _dataGridViewPatterns_KeyPress(object sender, KeyPressEventArgs e)
        {// select the first row in data drit that matches with the pattern' first letter
            //int selColumnIndex = _dataGridViewPatterns.SelectedCells[0].ColumnIndex;
            if (char.IsLetter(e.KeyChar))
            {
                char ch = char.ToUpper(e.KeyChar);
                int index = 0;
                foreach (char c in _dataGridViewPatterns.Rows.OfType<DataGridViewRow>().Select(dgvr => dgvr.Cells["PatternName"].Value.ToString()[0]))
                {
                    if (ch == char.ToUpper(c))
                    {
                        _dataGridViewPatterns.CurrentCell = _dataGridViewPatterns.Rows[index].Cells[0];
                        break;
                    }
                    index++;
                }
                //char[] namesFirstLetter = _dataGridViewPatterns.Rows.OfType<DataGridViewRow>().Select(dgvr => char.ToUpper(dgvr.Cells["PatternName"].Value.ToString()[0])).ToArray();
                //int index = Array.FindIndex<char>(namesFirstLetter, (n => n == ch));
                //if (index >= 0)
                //{
                //    _dataGridViewPatterns.CurrentCell = _dataGridViewPatterns.Rows[index].Cells[0];
                //}
            }
        }

        private void _contextMenuStrip_Opening(object sender, CancelEventArgs e)
        {
            hideShowFilters.Text = _splitContainerVertical.Panel1Collapsed ? "Show Filters' Panel" : "Hide Filters' Panel";
        }

        private void _buttonFiltersPanel_Click(object sender, EventArgs e)
        {
            WizardUtils.ShowFiltersPanel = _splitContainerVertical.Panel1Collapsed;
            _splitContainerVertical.Panel1Collapsed = !_splitContainerVertical.Panel1Collapsed;
            _buttonFiltersPanel.Text = _splitContainerVertical.Panel1Collapsed ? "Show Filters" : "Hide Filters";
        }

        private void _notifyIcon_BalloonTipClicked(object sender, EventArgs e)
        {

            string downloadUrl;
            float onlineVersion;
            //remove the time component to signal that the user saw the upgrade Msg
            Utils.LastOnlineCheck = DateTime.Today;
            if (Utils.NewOnlineVersionExists(out downloadUrl, out onlineVersion))
            {
                System.Diagnostics.Process.Start(string.IsNullOrEmpty(downloadUrl) ? Utils.BaseURL : downloadUrl);
                Utils.LastOnlineVer = onlineVersion.ToString(CultureInfo.InvariantCulture);
            }
            Utils.LastOnlineCheck = Utils.LastOnlineCheck.Date;
            _notifyIcon.Visible = false;
        }



        private void _contextMenuStripNotify_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
        {
            ContextMenuStrip s = sender as ContextMenuStrip;

            if (e.ClickedItem == toolStripMenuItemDownload)
            {
                _notifyIcon_BalloonTipClicked(sender, e);
            }
        }

        private void _contextMenuStripDescription_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
        {
            if (e.ClickedItem == _contextMenuStripDescription.Items[0])
            {
                ConfigForm cf = new ConfigForm(4);
                if (cf.ShowDialog(this) == DialogResult.OK)
                {
                    WBDescription.Tag = "";//force redraw
                    //WBDescription.Refresh();//avoids lock up on collapsibe headers????
                    WizardForm_Load(cf, null);
                    SetFilters();
                }
            }
        }
    }
}
